#!/usr/bin/env python
# -*- coding: UTF-8 -*-
"""
@Project ：pytest_allure_pytest-html_study 
@File    ：09_参数化.py
@IDE     ：PyCharm 
@Author  ：XiaoDengYa
@Date    ：2021/6/3/003 10:36 
"""
import pytest

"""
pytest允许在多个级别启用测试参数化：
 pytest.fixture() 允许fixture有参数化功能（后面讲解）
 @pytest.mark.parametrize 允许在测试函数或类中定义多组参数和fixtures
 pytest_generate_tests 允许定义自定义参数化方案或扩展（拓展）
 
 参数化场景
只有测试数据和期望结果不一样，但操作步骤是一样的测试用例可以用上参数化；
可以看看下面的栗子
"""
#
# def test_1():
#     assert 3 + 5 == 9
#
#
# def test_2():
#     assert 2 + 4 == 6
#
#
# def test_3():
#     assert 6 * 9 == 42

# 利用参数化优化之后的代码
"""
@pytest.mark.parametrize("test_input,expected", [("3+5", 8), ("2+4", 6), ("6*9", 42)])
def test_eval(test_input, expected):
    print(f"测试数据{test_input},期望结果{expected}")
    assert eval(test_input) == expected
"""

"""
实际Web UI自动化中的开发场景，比如是一个登录框
你肯定需要测试账号空、密码空、账号密码都为空、账号不存在、密码错误、账号密码正确等情况
这些用例的区别就在于输入的测试数据和对应的交互结果
所以我们可以只写一条登录测试用例，然后把多组测试数据和期望结果参数化，节省很多代码量
"""

"""
源码分析
def parametrize(self,argnames, argvalues, indirect=False, ids=None, scope=None): 
argnames
源码解析：a comma-separated string denoting one or more argument names, or a list/tuple of argument strings.
含义：参数名字
格式：字符串"arg1,arg2,arg3"【需要用逗号分隔】
备注：源码中写了可以是参数字符串的list或者tuple，但博主实操过是不行的，不知道是不是写的有问题，大家可以看看评论下
"""
# data_1 =[(1, 2,3), (3, 4,7), (7, 8,15)]

# 装饰测试类
"""
@pytest.mark.parametrize('a, b, expect', data_1)
class TestParametrize:

    def test_parametrize_1(self, a, b, expect):
        print('\n测试函数11111 测试数据为\n{}-{}'.format(a, b))
        assert a + b == expect

    def test_parametrize_2(self, a, b, expect):
        print('\n测试函数22222 测试数据为\n{}-{}'.format(a, b))
        assert a + b == expect
"""
# 重点：当装饰器 @pytest.mark.parametrize 装饰测试类时，会将数据集合传递给类的所有测试用例方法

# 笛卡尔积，组合数据
"""
data_1 = [1, 2, 3]
data_2 = ['a', 'b']


@pytest.mark.parametrize('a', data_1)
@pytest.mark.parametrize('b', data_2)
def test_parametrize_1(a, b):
    print(f'笛卡尔积 测试数据为 ： {a}，{b}')
"""
"""
重点知识
一个函数或一个类可以装饰多个 @pytest.mark.parametrize 
这种方式，最终生成的用例数是n*m，比如上面的代码就是：参数a的数据有3个，参数b的数据有2个，所以最终的用例数有3*2=6条
当参数化装饰器有很多个的时候，用例数都等于n*n*n*n*....
"""

# 参数化 ，传入字典数据

# 字典
"""
data_1 = (
    {
        'user': 1,
        'pwd': 2
    },
    {
        'user': 3,
        'pwd': 4
    }
)


@pytest.mark.parametrize('dic', data_1)
def test_parametrize_1(dic):
    print(f'测试数据为\n{dic}')
    print(f'user:{dic["user"]},pwd{dic["pwd"]}')
"""

# 参数化，标记数据
"""
@pytest.mark.parametrize("test_input,expected", [
    ("3+5", 8),
    ("2+4", 6),
    pytest.param("6 * 9", 42, marks=pytest.mark.xfail), # 标识用例执行失败
    pytest.param("6*6", 42, marks=pytest.mark.skip) # 直接跳过该用例
])
def test_mark(test_input, expected):
    assert eval(test_input) == expected
"""

# 参数化，增加可读性

data_1 = [
    (1, 2, 3),
    (4, 5, 9)
]

# ids
ids = ["a:{} + b:{} = expect:{}".format(a, b, expect) for a, b, expect in data_1] # 添加描述性语句


@pytest.mark.parametrize('a, b, expect', data_1, ids=ids)
class TestParametrize(object):

    def test_parametrize_1(self, a, b, expect):
        print('测试函数1测试数据为{}-{}'.format(a, b))
        assert a + b == expect

    def test_parametrize_2(self, a, b, expect):
        print('测试函数2数据为{}-{}'.format(a, b))
        assert a + b == expect


"""
知识点
多少组数据，就要有多少个id，然后组成一个id的列表
作用：主要是为了更加清晰看到用例的含义
"""
